import os, sys, shelve, collections, xmlrpclib, time, datetime, traceback
import cPickle as pickle
from SimpleXMLRPCServer import SimpleXMLRPCServer
import zlib
from bourbon.util import *

	
class JobRunner:
	
	def __init__(self):
		pass
		
	def save_experiment(self, experiment):
		pass
	
	def run_experiment(self, experiment, steps=4):
		"""Run the provided experiment.
			results - absolute path to the folder where experiment results should be stored. If nothing is provided, then results won't be stored.
		"""
		if experiment.is_finalized(): return
		
		if not experiment.is_started():
			experiment.start()
		
		done = 0.0
		start = datetime.datetime.now()
		print 'RUNNING EXPERIMENT [0] -- %s'%str(start)
		while not experiment.is_finished():
			experiment.advance(1.0/steps)
			self.save_experiment(experiment)
			done += 1.0/steps
			current = datetime.datetime.now()
			td = current - start
			duration = (td.microseconds + float(td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
			print 'RUNNING EXPERIMENT [%.0f] -- %s (%.2f sec remaining)'%(100*done, current, duration/done*(1-done))
			
		experiment.finalize()
		

class RPCJobRunner(JobRunner):
	
	def __init__(self, address="http://localhost:8000"):
		JobRunner.__init__(self)
		self._server = None
		self._address = address
		self._run = True
		
	def get_server(self):
		print 'Acquiring Server at ', self._address
		try:
			self._server = xmlrpclib.ServerProxy(self._address, allow_none=True)
			num = self._server.check()
		except:
			self._server = None
		
	def verify_server(self):
		while self._server is None:
			self.get_server()
			if self._server is None:
				time.sleep(5.0)
		
	def start(self):
		self.get_server()
		
		self.verify_server()
			
		while self._run:
			self.verify_server()
			job_id = -1
			try:
				job_id = self._server.get_next_work()
				if job_id <> -1:
					print 'Got Job [%d]'%job_id
					job_data = self._server.get_work_data(job_id, True)
			except:
				# Error receiving file, try again later
				traceback.print_exc()
				if job_id <> -1:
					self._server.checkout_success( job_id, False )
				job_id = -1
				
			if job_id == -1: 
				#self._run = False
				time.sleep(5.0)
			else:
				e_id = job_id
				exp_data = job_data
				self._server.checkout_success( job_id, True )
				print 'Got Job Size [%d]'%len(exp_data.data) 
				experiment = exp_from_data( exp_data.data )
				time1 = datetime.datetime.now()
				self.run_experiment(experiment, steps=10)
				td = datetime.datetime.now() - time1
				duration = (td.microseconds + float(td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
				results = experiment.results()
				
				# add duration to results
				results['Duration'] = duration
				
				data = xmlrpclib.Binary(pickle.dumps(results))
				print 'Submitting %d bytes'%len(data.data)
				print 'Submitting results for [%d]'%e_id
				self._server = None
				self.verify_server()
				
				#self._server.submit_results(e_id, pickle.dumps(results))
				self._server.submit_results_binary(e_id, data)
				del experiment
				del exp_data
		